#include <fstream>
#include <iostream>
#include <vector>
#include "yield_curve.h"
#include "CCreditCurve.h"
#include "american.h"
#include "interest_swap.h"
#include "convert_bond.h"
#include "BlackScholes.h"
#include "ImpliedVolBisection.h"
#include "MatrixRegression.h"
#include "Rainbows.h"
#include "stocks.h"
#include "mcnormal_vs.h"
#include "black_scholes_vs.h"
#include "variance_swap.h"
#include "bonds.h"

using namespace std;

void printDebug(vector<double> stks, vector<double> prs, vector<double> sis);

int main(int argc, char* argv[])
{
	
	//yield curve

	YieldCurve yc;
	yc.ReadSwapFile(USD, "input.txt");

	printf("Testing yield curve...\n\n");
	printf("Discount curve written to a file called 'df_result.txt'...\n");
	printf("Forward curve written to a file called 'fr_result.txt'...\n");
	printf("Spot curve written to a file called 'sr_result.txt'...\n\n");
	


	ofstream df_result_file("df_result.txt");
	ofstream fr_result_file("fr_result.txt");
	ofstream sr_result_file("sr_result.txt");

	vector<double> yield_curve_vec;
	vector<double> forward_rate_vec;
	vector<double> spot_rate_vec; 


	for (int i = 0; i < 60; i++) {
		double discount_factor = yc.DiscountFactor((double) i/2);
		// double forward_rate = yc.ForwardRate((double) i/2, ((double) i+1)/2);
		double spot_rate = yc.SpotRate((double) i/2);

		yield_curve_vec.push_back(discount_factor);
		// forward_rate_vec.push_back(forward_rate);
		spot_rate_vec.push_back(spot_rate);
	}

	for (int i = 0; i < 59; i++) {
		double forward_rate = yc.ForwardRate((double) i/2, ((double) i+1)/2);
		forward_rate_vec.push_back(forward_rate);
	}

	for (int i = 0; i < yield_curve_vec.size(); i++)
		df_result_file << yield_curve_vec[i] << endl;

	for (int i = 0; i < forward_rate_vec.size(); i++)
		fr_result_file << forward_rate_vec[i] << endl;

	for (int i = 0; i < spot_rate_vec.size(); i++)
		sr_result_file << spot_rate_vec[i] << endl;

	//credit curve ---------------------------------------

	printf("\nTesting credit curve...\n\n");
	printf("Credit Spread output written to file called 'CreditSpread.txt'...\n");
	printf("HazardRate output written to file called 'HazardRate.txt'...\n");
	printf("SurvivalProbability output written to file called 'SurvivalProbability.txt'...\n");


	CCreditCurve CreditCurve;

	CreditCurve.ReadCDSFile("Spreads.txt");

	vector<double> risky_discount; 
	ofstream rd_result_file("risky_discount.txt");

	for (int i = 0; i < 60; i++) {
		double discount_factor;
		discount_factor = CreditCurve.DiscountFactor((double) i/2);
		risky_discount.push_back(discount_factor);
		}

	for (int i = 0; i < risky_discount.size(); i++)
		{
		rd_result_file << risky_discount[i] << endl;
		}
	printf("RiskyDiscount output written to file called 'risky_discount.txt'...\n\n");

     //stocks --------------------------------------------------------


	printf("Testing stock price...\n\n");

	Stocks stock;

	stock.readData("input_stocks");

	stock.getForwardPrice();

	stock.printDebug();

     //bonds --------------------------------------------------------


	printf("\nTesting bonds...\n\n");

	Bonds bonds(30,2);
	bonds.setPrincipal(1000);
	bonds.setCouponPercent(.04);
	bonds.setfirstCouponDate(182);
	bonds.compute();
	cout << "Fair value of risk-free bond is: " << bonds.getFairValue(1) << endl;
	cout << "Duration of risk-free bond is: " << bonds.getDuration(1) << endl;
	cout << "Convexity of risk-free bond is: " << bonds.getConvexity(1) << endl;
	cout << "Fair value of risky bond is: " << bonds.getFairValue(2) << endl;
	cout << "Duration of risky bond is: " << bonds.getDuration(2) << endl;
	cout << "Convexity of risky bond is: " << bonds.getConvexity(2) << endl;
	bonds.printCashFlows();
	cout << "Cash flow output written to file called 'bond_cash_flows.txt' "<< endl;


    //volatility surface --------------------------------------------------------


	printf("\nTesting volatility surface...\n\n");
	
	double Price = 1177;
	double Strike;
	double Tdays;
	double RiskFree = .026;
	double DividendRate = .018;
	double OptionPrice;
	int size;

    // Read Option Data from File(Time in Days, Markets Prices, Strikes)
    // Stores these values in vectors.
 	FILE* regression_file;
	regression_file = fopen("optionsdatacomma2.csv", "r");
	
	vector<double> timeindays;
	vector<double> prices;
	vector<double> strikes;
	vector<double> betas;

	while (!feof(regression_file)) {
		double t;
        double s;
    	double k;

		fscanf(regression_file, "%lf %lf %lf", &t, &k, &s);
        timeindays.push_back(t);
        strikes.push_back(k);
        prices.push_back(s);
	}
    
	fclose(regression_file);
    
    size = prices.size()-1;
    vector<double> sigmas(size);
	
	/*
     * For each option visible in the market,
	 * we "back out" a sigma from the Black-Scholes formula.
	 * 
     * Uses the bisection method.         
	 */
	for (int m = 0; m < size; m++) {
	    OptionPrice = prices[m];
	    Strike = strikes[m];
	    Tdays = timeindays[m];
	    
	    sigmas[m] = FindImpliedVol(CALL, Price, Strike, Tdays/365,
								   RiskFree, DividendRate, OptionPrice);
    } 

	// If you want to print those implied volatility, delete the //
	// printDebug(strikes, prices, sigmas);

    // Regression
    Regression(Price, strikes, timeindays, sigmas, betas);

	printf("vol for strike of 40 and maturity = .5 is %5.10f\n",
              getVolatility(40,50,.5,betas[0],betas[1],betas[2]));





	//american options -------------------------------------------------------------------
	American opt;
	printf("\n\nTesting American Put...\n\n");
	opt.setUnderlyingValue(100);
	opt.setVol(getVolatility(100,100,1,betas[0],betas[1],betas[2])); 
	opt.setStrike(100);
	opt.setStrike2(110);
	opt.setStrike3(120);
	// opt.setInterest(.06); 
	double interest_rate = yc.SpotRate(1);
	opt.setInterest(interest_rate);
	opt.setTimeToMaturity(365);
	opt.setPutCallFlag(2);
	opt.setDividendRate(0);
	opt.setBetas(betas[0],betas[1],betas[2]);
	opt.compute();
	printf("Option price is is %5.10f\n", opt.getOptPrice());
	printf("Delta is %5.10f\n", opt.getDelta());
	printf("Gamma is %5.10f\n", opt.getGamma());
	printf("Theta is %5.10f\n", opt.getTheta());
	printf("Vega is %5.10f\n", opt.getVega());
	opt.printInputs();

	printf("\n\nTesting American Call...\n\n");
	opt.setPutCallFlag(1);
	opt.compute();
	printf("Option price is is %5.10f\n", opt.getOptPrice());
	printf("Delta is %5.10f\n", opt.getDelta());
	printf("Gamma is %5.10f\n", opt.getGamma());
	printf("Theta is %5.10f\n", opt.getTheta());
	printf("Vega is %5.10f\n", opt.getVega());
	opt.printInputs();
	printf("\n");

	printf("\nTesting Option Strategies...\n\n");
	opt.LongCallStraddle();
	printf("\n");
	opt.LongCallSpread();
	printf("\n");
	opt.LongButterflySpread();


//     Interest swap

	InterestSwap swap("input_interest_swap_file.txt");
	swap.compute();
	printf("\n\nTesting Interest Swap...\n\n");
	printf("Output written to file called 'swap_result.txt'...\n");

     //variance swap --------------------------------------------------------

	printf("\n\nTesting variance swap ...\n\n");
	
	VarianceSwap vs;

	vs.vs_readData("variance_swap_data.txt");
	
	double variance_swap = vs.getVarianceSwap();

	vs.vs_printDebug();

	cout << "the value of K_var is: " << variance_swap << endl;



//   Convertible bond

//   Convertible bond

	printf("\nTesting Convertible Bond...\n\n");
	Convert_bond cbond;
	cbond.setUnderlyingValue(40);
	cbond.setVol(.2);
	cbond.setStrike(120);
	cbond.setStrike2(90);
	cbond.setInterest(.06);
	cbond.setTimeToMaturity(365);
	cbond.setDividendRate(.01);
	cbond.setConversionRatio(2);
	cbond.setNotional(100);

	cbond.compute();
	printf("Total value is %5.10f\n", cbond.getFairValue());
	printf("Value due underlying bond is %5.10f\n", cbond.getBondValue());
	printf("Value due to expected conversion (whether forced via call or opted for) is %5.10f\n", cbond.getConversionValue());
	printf("Value due to put is %5.10f\n", cbond.getPutValue());
	printf("Parity delta is %5.10f\n", cbond.getParity_Delta());
	cout<<"Interest rate delta (in % points) is "<<cbond.getInterest_Rate_Delta()<<"."<<endl;
	printf("Parity Gamma is %5.10f\n", cbond.getParityGamma());

	cbond.printInputs();
	printf("\n\n");
	

// Rainbows() opt;-------------------------------------------------------------------------

printf("\nTesting Rainbow Options...\n\n");

Rainbows r_opt;
r_opt.setUnderlyingValues(100,100);
r_opt.setVols(.2,.2); //.2 = 20%
r_opt.setWeights(1,1);
r_opt.setStrike(20);
r_opt.setInterest(.06); //.06 = 6%
r_opt.setTimeToMaturity(365); //in calendar days
r_opt.setPutCallFlag(1); // 1 = call and -1 = put
r_opt.setCorrelation (.5);
r_opt.setSimNo(100000);

int i;
for (i=1; i<=6;i++)
{
	r_opt.setOptType(i);
	r_opt.compute();
	printf("Simulation price of the rainbow option is %5.10f\n", r_opt.getOptValue());
	printf("Delta of asset 1 is %5.10f\n",  r_opt.getDeltaAsset1());
	printf("Delta of asset 2 is %5.10f\n",  r_opt.getDeltaAsset2());
	printf("Gamma of asset 1 is %5.10f\n",  r_opt.getGammaAsset1());
	printf("Gamma of asset 2 is %5.10f\n",  r_opt.getGammaAsset2());
	printf("Vega of asset 1 is %5.10f\n",  r_opt.getVegaAsset1());
	printf("Vega of asset 2 is %5.10f\n",  r_opt.getVegaAsset2());
	printf("Correlation sensitivity is %5.10f\n",  r_opt.getCorrSens());
	r_opt.printInputs();
	printf("\n");
}



	return(0);
}

void printDebug(vector<double> stks, vector<double> prs, vector<double> sis)
{
	for (int i = 0; i < stks.size(); i++)
		cout << stks[i] << " " << prs[i] << " " << sis[i] << endl;
}


